﻿using HalconDotNet;
using Halcon二次开发.Model;
using Halcon二次开发.Model.储放所有单例.储存每个单例界面;
using Halcon二次开发.Model.自定义控件;
using Halcon二次开发.Tools;
using Halcon二次开发.View.工位监控画面;
using Halcon二次开发.View.相机;
using Halcon二次开发.View.配置界面;
using halcon联合.自定义控件;
using MvCameraControl;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Halcon二次开发.Controller.CamerForm交互
{
    public class CamerFormController
    {
        /// <summary>
        /// 初始路径，保存路径
        /// </summary>
        private string pathImage;
        /// <summary>
        /// 相机界面UI
        /// </summary>
        public CamerForm form;
        /// <summary>
        /// SDK图像 补丁 jjh
        /// </summary>
        HObject RunImage;
        Bitmap bitImage;
        public HwindowFlowNodeUrseControl hwindowFlowNode;
        #region 连接相机字段
        /// <summary>
        /// 海康SDK中的DeviceTLayerType是一个枚举类型，用于指定设备层的类型。在海康的SDK中，通过设置不同的
        /// DeviceTLayerType值，可以获取或设置设备的不同属性或执行特定的操作。
        /// </summary>
        readonly DeviceTLayerType enumTLayerType = DeviceTLayerType.MvGigEDevice
            | DeviceTLayerType.MvUsbDevice
            | DeviceTLayerType.MvGenTLGigEDevice
            | DeviceTLayerType.MvGenTLCXPDevice
            | DeviceTLayerType.MvGenTLCameraLinkDevice
            | DeviceTLayerType.MvGenTLXoFDevice;
        /// <summary>
        /// 设备基本信息集合
        /// </summary>
        List<IDeviceInfo> deviceInfoList = new List<IDeviceInfo>();
        /// <summary>
        ///  相机对象
        /// </summary>
        public IDevice device = null;
        /// <summary>
        /// 图像路径集合
        /// </summary>
        public List<string> Paths = new List<string>();
        /// <summary>
        /// 实时现实图像的窗口
        /// </summary>
        RealTimeCamerForm realTimeCamerForm;

        bool runPaper = false;

        Action<HImage> runAction;
        #endregion
        #region 控制参数
        public HObject HideOutputImage;
        #endregion
        public CamerFormController(HwindowFlowNodeUrseControl hwindowFlowNode, RealTimeCamerForm realTimeCamerForm, CamerForm form)
        {
            SDKSystem.Initialize();
            pathImage = $@"Data\工程文件\{hwindowFlowNode.projectName}\{hwindowFlowNode.name}任务文件\相机图片数据";
            //创建一个工程下保存图片的路径默认路径
            Directory.CreateDirectory(pathImage);
            this.form = form;
            this.hwindowFlowNode = hwindowFlowNode;
            this.realTimeCamerForm = realTimeCamerForm;
            runAction += Runing;
            //将上一次的相机图片进行赋值
            if (Directory.Exists(pathImage))
            {
                //相机一个工程只有一个相机
                if (File.Exists(pathImage + "\\" + "相机工具0.json"))
                {
                    Paths = HelpJsons.Read<string>(pathImage + "\\" + "相机工具0.json");
                }
                //显示缩放图上去
                foreach (string item in Paths)
                {
                    PictureBox pictureBox = new PictureBox();
                    //创建右击菜单
                    ContextMenuStrip contex = new ContextMenuStrip();
                    pictureBox.Name = item;
                    //增加一个删除选项
                    contex.Items.Add("删除图片", Image.FromFile("Data\\Image\\Exit2.png"));
                    contex.Items[0].Tag = pictureBox;
                    contex.Items[0].Click += CamerFormController_Click;
                    //绑定右击菜单
                    pictureBox.ContextMenuStrip = contex;
                    if (File.Exists(item))
                    {
                        pictureBox.Image = Image.FromFile(item);
                    }
                    pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    form.flowLayoutPanel1.Controls.Add(pictureBox);
                }
                if (Paths.Count > 0)
                {
                    //先显示一张图像上去
                    if (File.Exists(Paths[0]))
                    {
                        HideOutputImage = new HImage(Paths[0]);
                        hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                        //图像居中
                        hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                        form.label1.Text = "图像:共" + Paths.Count + "张";
                        count = 0;
                    }

                }
                Control.CheckForIllegalCrossThreadCalls = false;
            }
        }
        /// <summary>
        /// 图像索引
        /// </summary>
        public int count;
        /// <summary>
        /// 打开文件夹
        /// </summary>
        public void OpenDirectory(TextBox textBox, FlowLayoutPanel panel, Label label)
        {
            using (FolderBrowserDialog ofd = new FolderBrowserDialog())
            {
                this.Paths.Clear();
                // 设置描述文本（可选）  
                ofd.Description = "请选择一个文件夹";
                // 显示对话框  
                // 检查用户是否点击了“确定”  
                if (ofd.ShowDialog() == DialogResult.OK)
                {
                    // 用户选择了一个文件夹，获取其路径  
                    string selectedPath = ofd.SelectedPath;

                    string[] paths = Directory.GetFiles(selectedPath);
                    panel.Controls.Clear();
                    Paths.Clear();
                    //向原来的集合中追加图像路径
                    foreach (string item in paths)
                    {
                        //只有支持这些文件格式
                        if (item.Contains("PNG") || item.Contains("png") || item.Contains("jpg") || item.Contains("bmp"))
                        {
                            Paths.Add(item);
                            textBox.AppendText(item);
                        }
                    }
                    if (Paths.Count == 0) return;
                    //将图片路径进行一个保存
                    string imagePaths = pathImage + "\\" + this.form.Text + ".json";
                    HelpJsons.Write<string>(Paths, imagePaths);
                    //显示缩放图上去
                    foreach (string item in Paths)
                    {
                        PictureBox pictureBox = new PictureBox();
                        //创建右击菜单
                        ContextMenuStrip contex = new ContextMenuStrip();
                        pictureBox.Name = item;
                        //增加一个删除选项
                        contex.Items.Add("删除图片", Image.FromFile("Data\\Image\\Exit2.png"));
                        contex.Items[0].Tag = pictureBox;
                        contex.Items[0].Click += CamerFormController_Click;
                        //绑定右击菜单
                        pictureBox.ContextMenuStrip = contex;
                        pictureBox.Image = Image.FromFile(item);
                        pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                        panel.Controls.Add(pictureBox);
                    }
                    //先显示一张图像上去
                    HideOutputImage = new HImage(Paths[0]);
                    hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                    //图像居中
                    hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                    label.Text = "图像:共" + paths.Length + "张";
                    count = 0;
                }
            }
        }
        public void Write_ImagePath()
        {
            //将图片路径进行一个保存
            pathImage = $@"Data\工程文件\{hwindowFlowNode.projectName}\{hwindowFlowNode.name}任务文件\相机图片数据";
            if (!Directory.Exists(pathImage))
            {
                Directory.CreateDirectory(pathImage);
            }
            string imagePaths = pathImage + "\\" + this.form.Text + ".json";
            HelpJsons.Write<string>(Paths, imagePaths);
        }
        /// <summary>
        /// 打开文件
        /// </summary>
        public void OpenFile(TextBox textBox, FlowLayoutPanel panel, Label label)
        {
            this.Paths.Clear();
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "PNG文件|*.png*|JPEG文件|*.jpg*|BMP文件|*.bmp*";
            ofd.Multiselect = true;
            if (ofd.ShowDialog() == DialogResult.OK)
            {
                panel.Controls.Clear();
                //向原来的集合中追加图像路径
                foreach (string item in ofd.FileNames)
                {
                    Paths.Add(item);
                    textBox.AppendText(item);
                }
                //pathImage = 
                //将图片路径进行一个保存
                string imagePaths = $"Data\\工程文件\\{hwindowFlowNode.projectName}\\{hwindowFlowNode.name}任务文件\\相机图片数据\\相机工具0.json";
                HelpJsons.Write<string>(Paths, imagePaths);
                //显示缩放图上去
                foreach (string item in Paths)
                {
                    PictureBox pictureBox = new PictureBox();
                    //创建右击菜单
                    ContextMenuStrip contex = new ContextMenuStrip();
                    pictureBox.Name = item;
                    //增加一个删除选项
                    contex.Items.Add("删除图片", Image.FromFile("Data\\Image\\Exit2.png"));
                    contex.Items[0].Tag = pictureBox;
                    contex.Items[0].Click += CamerFormController_Click;
                    //绑定右击菜单
                    pictureBox.ContextMenuStrip = contex;
                    pictureBox.Image = Image.FromFile(item);
                    pictureBox.SizeMode = PictureBoxSizeMode.Zoom;
                    panel.Controls.Add(pictureBox);
                }
                //先显示一张图像上去
                HideOutputImage = new HImage(Paths[0]);
                hwindowFlowNode.hSmartWindowControl1.HalconWindow.DispObj(HideOutputImage);
                //图像居中
                hwindowFlowNode.hSmartWindowControl1.SetFullImagePart();
                //记录一下当前图像
                label.Text = "图像:共" + ofd.FileNames.Length + "张";
                count = 0;
            }
        }
        public void PushIntputImage()
        {

        }

        /// <summary>
        /// 删除按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CamerFormController_Click(object sender, System.EventArgs e)
        {
            ToolStripMenuItem toolStrip = (ToolStripMenuItem)sender;
            PictureBox node = (PictureBox)toolStrip.Tag;
            string path = node.Name;
            //记录删除之前的位置
            int index = node.Parent.Controls.IndexOf(node);
            node.Parent.Controls.Remove(node);
            Paths.Remove(path);
            //要获取对应对象中的count
            hwindowFlowNode.count = index - 1;
            //将图片路径进行一个保存
            string imagePaths = pathImage + "\\" + this.form.Text + ".json";
            HelpJsons.Write<string>(Paths, imagePaths);
            (FormDb.Db["Form1"] as Form1).textBox1.AppendText("注意已删除图层!\r\n");
            form.label1.Text = "图像:共" + Paths.Count + "张";
        }
        /// <summary>
        /// 刷新设备集合
        /// </summary>
        /// <param name="deviceBox">combox控件</param>
        /// <returns></returns>
        public List<IDeviceInfo> RefreshDeviceList()
        {
            deviceInfoList.Clear();
            //获取所有相机设备
            int oRet = DeviceEnumerator.EnumDevices(enumTLayerType, out deviceInfoList);
            if (oRet != MvError.MV_OK)
            {
                return null;
            }
            return deviceInfoList;
        }
        /// <summary>
        /// 打开相机设备
        /// </summary>
        /// //相机设备信息
        IEnumValue triggerSelector = null;  // 触发选项
        IEnumValue triggerMode = null;      // 触发模式
        IEnumValue triggerSource = null;    // 触发源
        IEnumValue pixelFormat = null;      // 像素格式 
        IEnumValue triggerActivation = null; //触发极性
        IEnumValue lineSelector = null;    //输入输出源
        IEnumValue lineMode = null;     //输出模式
        IFloatValue exposureTime = null;  //曝光时间
        IFloatValue acquisitionFrameRate = null;  //帧率
        IFloatValue gain = null;  //增益
        public Thread thread;
        public bool paper = true;
        public CancellationTokenSource cancellationTokenSource;

        /// <summary>
        /// 打开相机连接
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public bool OpenCamer(int index)

        {
            try
            {
                //通过相机设备创建相机对象
                device = DeviceFactory.CreateDevice(deviceInfoList[index]);
                device.StreamGrabber.FrameGrabedEvent += StreamGrabber_FrameGrabedEvent;

            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), "error");
            }
            //打开连接
            int ok = device.Open();
            if (ok != MvError.MV_OK)
            {
                MessageBox.Show("Open Device fail!" + ok);
                return false;
            }
            cancellationTokenSource = new CancellationTokenSource();
            CancellationToken token = cancellationTokenSource.Token;
            this.paper = true;
            Task.Run(async () =>
            {
                while (paper && !token.IsCancellationRequested)
                {
                    try
                    {
                        await Task.Delay(10).ConfigureAwait(false);
                        DeviceEnumerator.EnumDevices(enumTLayerType, out List<IDeviceInfo> deviceInfoList);
                        // 判断当前设备是否还存在于设备列表中
                        if (!deviceInfoList.Any(d => d.SerialNumber == device.DeviceInfo.SerialNumber))
                        {
                            await Task.Delay(2).ConfigureAwait(false);
                            DeviceEnumerator.EnumDevices(enumTLayerType, out List<IDeviceInfo> deviceInfoList2);
                            if (!deviceInfoList2.Any(d => d.SerialNumber == device.DeviceInfo.SerialNumber))
                            {
                                paper = false;

                                var tasks = StaicResouce.HomeForms.Select(async item =>
                                {
                                    if (form.HwindowFlowNode.projectName == ((HwindowFlowNodeUrseControl)item).projectName)
                                    {
                                        var control = (HwindowFlowNodeUrseControl)item;
                                        control.camerFormController?.LevelReversal();
                                        control.runPaper = false;

                                        // 如果当前线程不是 UI 线程，使用 BeginInvoke 转到 UI 线程执行
                                        await Task.Run(() =>
                                        {
                                            control.BeginInvoke((Action)(() =>
                                            {
                                                // 启动闪烁
                                                control.framesTimeForm.indicatorLight1.State = IndicatorLight.IndicatorState.RedBlinking; // 切换为红色闪烁
                                                control.runPaper = false;
                                            }));
                                        });
                                    }
                                }).ToArray();

                                // await Task.WhenAll(tasks);  // 等待所有并行任务完成

                                CamerGG();
                            }
                        }
                    }
                    catch (Exception ex)
                    {

                    }
                }

            });
            //ch: 设置合适的缓存节点数量 | en: Setting the appropriate number of image nodes
            device.StreamGrabber.SetImageNodeNum(5);
            //*
            if (device is IGigEDevice)
            {
                //ch: 转换为gigE设备 | en: Convert to Gige device
                IGigEDevice gigEDevice = device as IGigEDevice;
                // ch:探测网络最佳包大小(只对GigE相机有效) | en:Detection network optimal package size(It only works for the GigE camera)
                int optionPacketSize;
                int result = gigEDevice.GetOptimalPacketSize(out optionPacketSize);
                if (result != MvError.MV_OK)
                {
                    MessageBox.Show("Warning: Get Packet Size failed!" + result);
                    return false;
                }
                else
                {
                    result = device.Parameters.SetIntValue("GevSCPSPacketSize", (long)optionPacketSize);
                    if (result != MvError.MV_OK)
                    {
                        MessageBox.Show("Warning: Set Packet Size failed!" + result);
                        return false;
                    }
                }
            }
            SetExposure(float.Parse(form.numericUpDown1.Value.ToString()));//设置曝光时间
            SetGain(float.Parse(form.numericUpDown2.Value.ToString()));//设置增益
            SetAcquisitionFrameRate(float.Parse(form.numericUpDown4.Value.ToString()));//设置帧率

            //回调函数
            device.Parameters.SetEnumValueByString("TriggerMode", "Off");// 触发模式关闭
            int StartResult = device.StreamGrabber.StartGrabbing();//开始采集

            if (StartResult != MvError.MV_OK)
            {
                return false;
            }
            //将设备触发
            //form.comboBox2.Items.Add();
            //触发模式triggerMode
            device.Parameters.GetEnumValue("TriggerMode", out triggerMode);
            //触发选项triggerSelector
            device.Parameters.GetEnumValue("TriggerSelector", out triggerSelector);//AcquisitionStart
            //触发源triggerSource
            device.Parameters.GetEnumValue("TriggerSource", out triggerSource);//Software软触发   Line0;硬触发线路0
            //像素格式
            device.Parameters.GetEnumValue("PixelFormat", out pixelFormat);//8位图
            //触发极性TriggerActivation
            device.Parameters.GetEnumValue("TriggerActivation", out triggerActivation);
            //获取输入输出源
            device.Parameters.GetEnumValue("LineSelector", out lineSelector);
            //获取输出模式lineMode
            device.Parameters.GetEnumValue("LineMode", out lineMode);
            try
            {
                UploadcomboBox();
            }
            catch { }
            return true;
        }
        public void CamerGG()
        {
            cancellationTokenSource.Cancel();
            paper = false;
            MessageBox.Show(hwindowFlowNode.name + "工位_相机断开链接", "警告", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            form.label8.Text = "未初始化取相";
            form.label8.ForeColor = System.Drawing.Color.Black;
            form.button6.Enabled = true; ;
            form.button7.Enabled = false;
            //form.comboBox2.Items.Clear();
            //form.comboBox3.Items.Clear();
            //form.comboBox4.Items.Clear();
            //form.comboBox5.Items.Clear();
            //form.comboBox6.Items.Clear();
            //form.comboBox1.Text = "";
            form.controller.triggerSourcePaper = false;
            form.controller.triggerModePaper = false;
        }
        /// <summary>
        /// 获取当前设备的增益，曝光时间，帧率
        /// </summary>
        public void GetCamerFoloat()
        {
            if (device != null)
            {
                device.Parameters.GetFloatValue("ExposureTime", out exposureTime);//曝光时间
                device.Parameters.GetFloatValue("AcquisitionFrameRate", out acquisitionFrameRate);//帧率
                device.Parameters.GetFloatValue("Gain", out gain);//增益
            }
        }
        /// <summary>
        /// 加载相机窗体中的数据
        /// </summary>
        private void UploadcomboBox()
        {
            try
            {
                foreach (var item in triggerMode.SupportEnumEntries)
                {
                    form.comboBox2.Items.Add(item.Symbolic.ToString());
                    //form.comboBox2.SelectedIndex = 0;
                }
                foreach (var item in triggerSelector.SupportEnumEntries)
                {
                    form.comboBox3.Items.Add(item.Symbolic.ToString());
                    //form.comboBox3.SelectedIndex = 0;
                }
                foreach (var item in triggerSource.SupportEnumEntries)
                {
                    form.comboBox4.Items.Add(item.Symbolic.ToString());
                    //form.comboBox4.SelectedIndex = 0;
                }
                foreach (var item in pixelFormat.SupportEnumEntries)
                {
                    form.comboBox5.Items.Add(item.Symbolic.ToString());
                    // form.comboBox5.SelectedIndex = 0;
                }
                foreach (var item in triggerActivation.SupportEnumEntries)
                {
                    form.comboBox6.Items.Add(item.Symbolic.ToString());
                    //form.comboBox6.SelectedIndex = 0;
                }
                //加载输出信息
                form.comboBox7.Items.Clear();//清空列表
                foreach (var item in lineSelector.SupportEnumEntries)
                {
                    form.comboBox7.Items.Add(item.Symbolic.ToString());
                }
                if (lineSelector.SupportEnumEntries.Length > 2)
                {
                    //form.comboBox7.SelectedIndex = 1;
                }
                //else form.comboBox7.SelectedIndex = 0;
                //加载Output
                foreach (var item in lineMode.SupportEnumEntries)
                {
                    form.comboBox8.Items.Add(item.Symbolic.ToString());
                    // form.comboBox8.SelectedIndex = 0;
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 更改相机属性
        /// </summary>
        //相机硬触发的开启标志位
        public bool triggerModePaper = false;
        //相机硬触发标志位
        public bool triggerSourcePaper = false;
        public void SetCamerMode()
        {

            try
            {
                int modePaper = 0;

                //取消图片线程int StartResult = device.StreamGrabber.StartGrabbing();//开始采集
                int StartResult = device.StreamGrabber.StopGrabbing();//停止采集，只有停止采集了才可以设置这些属性
                                                                      //修改触发模式(uint)triggerSource.SupportEnumEntries[form.comboBox4.SelectedIndex].Value
                                                                      //相机触发源
                modePaper = device.Parameters.SetEnumValueByString("TriggerSource", form.comboBox4.Text);
                ModeException(modePaper);
                //相机触发模式
                modePaper = device.Parameters.SetEnumValueByString("TriggerMode", form.comboBox2.Text);
                ModeException(modePaper);
                //相机触发选项
                modePaper = device.Parameters.SetEnumValueByString("TriggerSelector", form.comboBox3.Text);
                ModeException(modePaper);
                //相机像素格式
                modePaper = device.Parameters.SetEnumValueByString("PixelFormat", form.comboBox5.Text);
                //相机触发极性
                modePaper = device.Parameters.SetEnumValueByString("TriggerActivation", form.comboBox6.Text);
                ModeException(modePaper);
                //标志模式是不是硬触发模式
                if (!form.comboBox4.Text.ToString().Equals("Software"))
                {
                    triggerSourcePaper = true;
                    if (form.comboBox2.Text.ToString().Equals("On"))
                    {
                        triggerModePaper = true;
                    }
                    else
                    {
                        triggerModePaper = false;
                    }
                }
                else
                {
                    triggerSourcePaper = false;
                }
                //开始采集
                StartResult = device.StreamGrabber.StartGrabbing();//开始采集
            }
            catch { }
        }
        /// <summary>
        /// 当界面选择输出事件更改时触发
        /// </summary>
        public void SetOutMode()
        {
            int modePaper = 0;
            modePaper = device.Parameters.SetEnumValueByString("LineSelector", form.comboBox7.Text);
            ModeException(modePaper, "相机硬触发输出信号配置失败");
            //LineMode
            modePaper = device.Parameters.SetEnumValueByString("LineMode", form.comboBox8.Text);
            ModeException(modePaper, "相机硬触发输出信号配置失败");
        }
        /// <summary>
        /// 电平反转，输出电信号
        /// </summary>
        public void LevelReversal()
        {
            //只有硬触发时才会进入到这个条件
            if (triggerSourcePaper && triggerModePaper)
            {
                if (!device.IsConnected) return;
                int modePaper = 0;
                modePaper = device.Parameters.SetBoolValue("LineInverter", true);
                ModeException(modePaper, "输出信号失败,");
                //电平持续时间
                Thread.Sleep((int)form.numericUpDown5.Value);
                modePaper = device.Parameters.SetBoolValue("LineInverter", false);
                ModeException(modePaper, "输出信号失败,");
            }
        }
        /// <summary>
        /// 控制最大并发数量
        /// </summary>
       // SemaphoreSlim semaphore = new SemaphoreSlim(16);
        /// <summary>
        /// 相机采图访问的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        /// <summary>
        /// 相机采图访问的回调函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public async void StreamGrabber_FrameGrabedEvent(object sender, FrameGrabbedEventArgs e)
        {
            // 如果启用了硬触发
            if (triggerModePaper && triggerSourcePaper && hwindowFlowNode.runPaper)
            {
                
                // 异步执行处理逻辑

                //await semaphore.WaitAsync().ConfigureAwait(false);
                await Task.Delay(1).ConfigureAwait(false);

                try
                {
                    using (var frameCopy = (IFrameOut)e.FrameOut.Clone())
                    {
                        // 异步生成图像
                        HOperatorSet.GenImage1(out RunImage, "byte",
                                frameCopy.Image.Width,
                                frameCopy.Image.Height,
                                frameCopy.Image.PixelDataPtr);

                        if (RunImage != null && RunImage.IsInitialized())
                        {

                            // 异步硬触发处理
                            //hwindowFlowNode.HardTriggerRun(RunImage, okNum);
                            HObject hImage= RunImage.Clone();
                            // 显示结果图像（主线程操作）
                            // realTimeCamerForm.hSmartWindowControl1.HalconWindow.DispObj(RunImage);
                            //ok个数加1 将图像添加进处理队列

                            Interlocked.Increment(ref hwindowFlowNode.okCount);
                            hwindowFlowNode.imageHardRunData.Enqueue(hImage);
                        }
                    }
                }
                catch
                {

                }
                finally
                {
                    e.FrameOut.Dispose();
                   // semaphore.Release();
                }


            }
            else
            {
                // 非硬触发逻辑
                //await semaphore.WaitAsync();

                try
                {
                    using (var frameCopy = (IFrameOut)e.FrameOut.Clone())
                    {
                        HOperatorSet.GenImage1(out RunImage, "byte",
                               frameCopy.Image.Width,
                               frameCopy.Image.Height,
                               frameCopy.Image.PixelDataPtr);

                        if (RunImage != null && RunImage.IsInitialized())
                        {
                            realTimeCamerForm?.hSmartWindowControl1.HalconWindow.DispObj(RunImage);
                        }
                    }
                }
                catch
                {

                }
                finally
                {
                    e.FrameOut.Dispose();
                    //semaphore.Release();
                }

            }

        }

        //private async void StreamGrabber_FrameGrabedEvent(object sender, FrameGrabbedEventArgs e)
        //{
        //    try
        //    {
        //        Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
        //        await Task.Delay(1).ConfigureAwait(false);
        //        // 硬触发处理
        //        if (triggerModePaper && triggerSourcePaper && hwindowFlowNode.runPaper)
        //        {
        //            await semaphore.WaitAsync().ConfigureAwait(false);
        //            using (var frameCopy = (IFrameOut)e.FrameOut.Clone())
        //            {
        //                lock (semaphore)
        //                {
        //                    HOperatorSet.GenImage1(out RunImage, "byte",
        //                    frameCopy.Image.Width,
        //                    frameCopy.Image.Height,
        //                    frameCopy.Image.PixelDataPtr);
        //                }
        //            }
        //            if (RunImage != null && RunImage.IsInitialized())
        //            {
        //                //硬触发一次，ok个数加一
        //                hwindowFlowNode.HardTriggerRun(RunImage);
        //                //  await ProcessTriggerAsync(RunImage);
        //            }
        //            realTimeCamerForm.hSmartWindowControl1.HalconWindow.DispObj(RunImage);
        //        }
        //        else
        //        {
        //            await semaphore.WaitAsync().ConfigureAwait(false);
        //            using (var frameCopy = (IFrameOut)e.FrameOut.Clone())
        //            {
        //                lock (semaphore)
        //                {
        //                    HOperatorSet.GenImage1(out RunImage, "byte",
        //                    frameCopy.Image.Width,
        //                    frameCopy.Image.Height,
        //                    frameCopy.Image.PixelDataPtr);
        //                }
        //            }
        //            realTimeCamerForm.hSmartWindowControl1.HalconWindow.DispObj(RunImage);
        //        }

        //        //Thread.CurrentThread.Priority = ThreadPriority.AboveNormal;
        //        //await semaphore.WaitAsync().ConfigureAwait(false);
        //        //await Task.Delay(1).ConfigureAwait(false);
        //        //// 深拷贝图像数据
        //        //using (var frameCopy = (IFrameOut)e.FrameOut.Clone())
        //        //{

        //        //    HOperatorSet.GenImage1(out RunImage, "byte",
        //        //        frameCopy.Image.Width,
        //        //        frameCopy.Image.Height,
        //        //        frameCopy.Image.PixelDataPtr);

        //        //    realTimeCamerForm.hSmartWindowControl1.HalconWindow.DispObj(RunImage);
        //        //    // 确保图像对象不为 null
        //        //    if (RunImage != null && RunImage.IsInitialized())
        //        //    {
        //        //        // 硬触发处理
        //        //        if (triggerModePaper && triggerSourcePaper && hwindowFlowNode.runPaper)
        //        //        {
        //        //            //硬触发一次，ok个数加一
        //        //            hwindowFlowNode.HardTriggerRun(RunImage);
        //        //            //  await ProcessTriggerAsync(RunImage);
        //        //        }
        //        //    }
        //        //}
        //    }
        //    catch
        //    {

        //    }
        //    finally
        //    {

        //        e.FrameOut.Dispose();
        //        semaphore.Release();
        //    }
        //}

        /// <summary>
        /// 处理相机配置异常码
        /// </summary>
        /// <param name="modeRunPaper">异常码</param>
        /// <param name="text">可选文本，附加内容</param>
        private void ModeException(int modeRunPaper, string text = "")
        {
            try
            {
                if (modeRunPaper != 0)
                {
                    (FormDb.Db["Form1"] as Form1).textBox1.AppendText(HelpGetTiem.Getyyymmddmmss() + $": {text}相机配置失败，异常码为:" + ":" + modeRunPaper + "\r\n");
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 关闭取相
        /// </summary>
        /// <returns></returns>
        public bool CloseCamer()
        {
            try
            {
                cancellationTokenSource.Cancel();
                int reuslt = device.StreamGrabber.StopGrabbing();
                if (reuslt != MvError.MV_OK)
                {
                    return false;
                }
                else
                {
                    device.Parameters.SetEnumValueByString("TriggerMode", "On");
                    device.Close();
                    device.Dispose();
                    paper = false;
                    device = null;
                    return true;
                }
            }
            catch
            {
                return true;
            }
        }
        /// <summary>
        /// 运行按钮
        /// </summary>
        public void Run()
        {
            if (form.tabControl1.SelectedIndex == 0)
            {
                //图片
                if (device != null)
                {
                    runPaper = true;
                }
                //文件图像 如果没有图像文件
                if (Paths.Count == 0)
                {
                    throw new Exception("没有图像文件");
                }
                count++;
                //尾部
                if (count == Paths.Count)
                {
                    count = 0;
                }
                //对当前图像对象进行更新 
                HideOutputImage = new HImage(Paths[count]);
            }

            if (form.tabControl1.SelectedIndex == 1)
            {
                if (device == null)
                {
                    throw new Exception("未初始化取相");
                }
                else
                {
                    this.HideOutputImage = RunImage;
                }
            }
        }
        /// <summary>
        /// 运行后获取图像的委托
        /// </summary>
        /// <param name="obj"></param>
        private void Runing(HImage image)
        {
            runPaper = false;
            HSmartWindowControl hw = hwindowFlowNode.hSmartWindowControl1;
            hw.HalconWindow.DispObj(image);
            hw.SetFullImagePart();
        }
        /// <summary>
        /// 当前对象被强行关闭时释放资源
        /// </summary>
        public void Closed()
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValueByString("TriggerMode", "On");
                    device.Close();
                    device.Dispose();
                    device = null;
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 设置曝光
        /// </summary>
        /// <param name="value"></param>
        public void SetExposure(float value)
        {
            try
            {
                if (device != null)
                {
                    int result = device.Parameters.SetFloatValue("ExposureTime", value);
                }
            }
            catch
            {

            }

        }
        /// <summary>
        /// 设置增益
        /// </summary>
        /// <param name="value"></param>
        public void SetGain(float value)
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValue("GainAuto", 0);//关闭自动增益功能，增益才能生效
                    int result = device.Parameters.SetFloatValue("Gain", value);
                }
            }
            catch
            {

            }
        }
        /// <summary>
        /// 采集帧率
        /// </summary>
        /// <param name="value"></param>
        public void SetAcquisitionFrameRate(float value)
        {
            try
            {
                if (device != null)
                {
                    device.Parameters.SetEnumValue("ExposureAuto", 0);
                    int result = device.Parameters.SetFloatValue("AcquisitionFrameRate", value);
                }
            }
            catch (Exception e) { }
        }
        /// <summary>
        /// 设置IP地址
        /// </summary>
        public void SetIP()
        {
            if (deviceInfoList.Count == 0)
            {
                throw new Exception("无相机任何设备!\r\n");
            }
            IDevice device = DeviceFactory.CreateDevice(deviceInfoList[form.comboBox1.SelectedIndex]);

            IGigEDevice gigeDevice = device as IGigEDevice;

            //手动设置IP
            try
            {
                if (false == IPAddress.TryParse(form.textBox2.Text, out IPAddress address))
                {
                    throw new Exception("IP设置不符合要求!\r\n");
                }
                long nIP = IPAddress.NetworkToHostOrder(address.Address);
                //掩码转换
                if (false == IPAddress.TryParse("255.255.255.0", out IPAddress clsSubMask))
                {
                    throw new Exception("掩码设置不符合要求!\r\n");
                }
                long nSubMask = IPAddress.NetworkToHostOrder(clsSubMask.Address);

                // ch:网关转换 | en:Gateway conversion
                IPAddress clsDefaultWay;
                string[] defaultIP = form.textBox2.Text.Split('.');
                defaultIP[defaultIP.Length - 1] = "0";
                string strDefaultIP = "";
                for (int i = 0; i < defaultIP.Length; i++)
                {
                    if (i == defaultIP.Length - 1)
                    {
                        strDefaultIP += defaultIP[i];
                        break;
                    }
                    strDefaultIP += defaultIP[i] + ".";
                }
                if (false == IPAddress.TryParse(strDefaultIP, out clsDefaultWay))
                {
                    throw new Exception("默认网关设置不符合要求!\r\n");
                }
                long nDefaultWay = IPAddress.NetworkToHostOrder(clsDefaultWay.Address);
                // ch:判断设备IP是否可达 | en: If device ip is accessible
                bool accessible = DeviceEnumerator.IsDeviceAccessible(deviceInfoList[form.comboBox1.SelectedIndex], DeviceAccessMode.AccessExclusive);
                if (accessible)
                {
                    int ret = gigeDevice.SetIpConfig(IpConfigType.Static);

                    if (MvError.MV_OK != ret)
                    {
                        gigeDevice.Dispose();
                        throw new Exception("IP设置失败!\r\n");
                    }

                    ret = gigeDevice.ForceIp((uint)(nIP >> 32), (uint)(nSubMask >> 32), (uint)(nDefaultWay >> 32));
                    if (MvError.MV_OK != ret)
                    {
                        gigeDevice.Dispose();
                        throw new Exception("IP设置失败!\r\n");
                    }
                    // ch:最后判断设备IP是否可与电脑通信
                    accessible = DeviceEnumerator.IsDeviceAccessible(deviceInfoList[form.comboBox1.SelectedIndex], DeviceAccessMode.AccessExclusive);
                    if (!accessible) throw new Exception("设置的iP无法与相机通信!\r\n");
                }
                else
                {
                    //只有电脑与相机不在同一网段上才进入这个else条件中
                    int ret = gigeDevice.ForceIp((uint)(nIP >> 32), (uint)(nSubMask >> 32), (uint)(nDefaultWay >> 32));
                    if (MvError.MV_OK != ret)
                    {
                        throw new Exception("IP设置失败!\r\n");
                    }

                    IDeviceInfo deviceInfo = deviceInfoList[form.comboBox1.SelectedIndex];
                    IGigEDeviceInfo gigeDevInfo = deviceInfo as IGigEDeviceInfo;

                    uint nIp1 = ((gigeDevInfo.NetExport & 0xff000000) >> 24);
                    uint nIp2 = ((gigeDevInfo.NetExport & 0x00ff0000) >> 16);
                    uint nIp3 = ((gigeDevInfo.NetExport & 0x0000ff00) >> 8);
                    uint nIp4 = (gigeDevInfo.NetExport & 0x000000ff);
                    string netExportIp = nIp1.ToString() + "." + nIp2.ToString() + "." + nIp3.ToString() + "." + nIp4.ToString();
                    //ch:需要重新创建句柄，设置为静态IP方式进行保存 | en:  Need to recreate the handle and set it to static IP mode for saving
                    //ch: 创建设备 | en: Create device
                    device = DeviceFactory.CreateDeviceByIp(form.textBox2.Text, netExportIp);

                    if (null == device)
                    {
                        throw new Exception("IP设置失败!\r\n");
                    }
                    gigeDevice = device as IGigEDevice;
                    ret = gigeDevice.SetIpConfig(IpConfigType.Static);
                    if (MvError.MV_OK != ret)
                    {
                        gigeDevice.Dispose();
                        throw new Exception("IP设置失败!\r\n");
                    }
                    device.Dispose();
                    device.Close();
                }
            }
            catch (Exception ex)
            {
                device.Dispose();
                device.Close();
                throw ex;
            }
        }
        /// <summary>
        /// 设置曝光时间
        /// </summary>
        /// <param name="value"></param>
        public void SetExposureTime(float value)
        {
            //exposureTime  曝光时间对象   
            try
            {
                if (device != null)
                {
                    int result = device.Parameters.SetFloatValue("ExposureTime", value);
                }
            }
            catch
            {

            }
        }
    }

}
